`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 2024/12/17 10:10:02
// Design Name:
// Module Name: vesa_data
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////


module vesa_data(
    input                   clk_119m    ,
    input                   rst_n       ,

    output                  o_video_hs  ,
    output                  o_video_de  ,
    output                  o_video_vs  ,
    output  [23:0]          o_video_data
);

parameter       P_POLARITY          =   1   ;

parameter       P_HSYNC             =   176  ;
parameter       P_HSYNC_BP          =   280  ;
parameter       P_HSYNC_ACTIVE      =   1680 ;
parameter       P_HSYNC_FP          =   104  ;
parameter       P_HSYNC_TOTAL       =   2240 ;
parameter       P_HSYNC_START       =   1784 ;
parameter       P_HSYNC_END         =   1960 ;


parameter       P_VSYNC             =   6   ;
parameter       P_VSYNC_BP          =   30  ;
parameter       P_VSYNC_ACTIVE      =   1050;
parameter       P_VSYNC_FP          =   3   ;
parameter       P_VSYNC_TOTAL       =   1089;
parameter       P_VSYNC_START       =   1053;
parameter       P_VSYNC_END         =   1059;

//define reg
reg [2:0]   r_rst_cnt = 3'd0;
reg [15:0]  r_hs_cnt;
reg [15:0]  r_vs_cnt;
reg [15:0]  r_de_cnt;
reg [23:0]  r_video_data;
reg         ro_video_vs  ;
reg         ro_video_hs  ;
reg         ro_video_de  ;

// wire        w_vsync_valid;
// wire        w_hsync_valid;
wire        w_video_hs;
wire        w_video_vs;
wire        w_video_de;
// wire [23:0] w_video_data;
wire        rstn_sync;

//define assign
assign o_video_data     =  r_video_data ;
assign o_video_vs       =  ro_video_vs  ;
assign o_video_hs       =  ro_video_hs  ;
assign o_video_de       =  ro_video_de  ;
assign rstn_sync        = r_rst_cnt[2];
assign w_video_hs       =  r_hs_cnt <= P_HSYNC - 1 ? 1'd0 : 1'd1;
assign w_video_vs       =  r_vs_cnt <= P_VSYNC - 1 ? 1'd0 : 1'd1;
assign w_video_de       =  (r_hs_cnt >= P_HSYNC + P_HSYNC_BP)
                            & (r_hs_cnt <= P_HSYNC + P_HSYNC_BP + P_HSYNC_ACTIVE - 1)
                            & (r_vs_cnt >= P_VSYNC + P_VSYNC_BP)
                            & (r_vs_cnt <= P_VSYNC + P_VSYNC_BP + P_VSYNC_ACTIVE - 1);


always @(posedge clk_119m) begin
    if(~rst_n)
        r_rst_cnt <= 3'd0;
    else if(r_rst_cnt[2] == 1'd0)
        r_rst_cnt <= r_rst_cnt + 1'd1;
    else
        r_rst_cnt <= r_rst_cnt;
end


always @(posedge clk_119m) begin
    if(~rstn_sync)
        r_video_data <= 24'hffffff;
    else if(w_video_de == 0)
        r_video_data <= 24'hffffff;
    else if(r_de_cnt < P_HSYNC_ACTIVE/4)
        r_video_data <= 24'hff0000;
    else if(r_de_cnt >= P_HSYNC_ACTIVE/4 - 1 && r_de_cnt < (P_HSYNC_ACTIVE/4*2))
        r_video_data <= 24'h00ff00;
    else if(r_de_cnt >= P_HSYNC_ACTIVE/4*2 - 1 && r_de_cnt < (P_HSYNC_ACTIVE/4*3))
        r_video_data <= 24'h0000ff;
    else if(r_de_cnt < P_HSYNC_ACTIVE)
        r_video_data <= 24'h000000;
    else
        r_video_data <= 24'hffffff;
end

//define always module
always @(posedge clk_119m) begin
    if(~rstn_sync) begin
        r_hs_cnt <= 0;
    end
    else if(r_hs_cnt == P_HSYNC_TOTAL - 1)
        r_hs_cnt <= 0;
    else begin
        r_hs_cnt <= r_hs_cnt + 1;
    end
end

always @(posedge clk_119m) begin
    if(~rstn_sync) begin
        r_vs_cnt <= 0;
    end
    else if(r_hs_cnt == P_HSYNC_TOTAL - 1 && r_vs_cnt == P_VSYNC_TOTAL -1)
        r_vs_cnt <= 0;
    else if(r_hs_cnt == P_HSYNC_TOTAL - 1)begin
        r_vs_cnt <= r_vs_cnt + 1;
    end
    else
        r_vs_cnt <= r_vs_cnt;
end

always @(posedge clk_119m) begin
    if(~rstn_sync) begin
        r_de_cnt <= 0;
    end
    else if(w_video_de)
        r_de_cnt <= r_de_cnt + 16'd1;
    else
        r_de_cnt <= 16'd0;
end


always @(posedge clk_119m) begin
    if(~rstn_sync) begin
        ro_video_vs  <= 1'd0;
        ro_video_hs  <= 1'd0;
        ro_video_de  <= 1'd0;
    end
    else begin
        ro_video_vs  <= w_video_vs;
        ro_video_hs  <= w_video_hs;
        ro_video_de  <= w_video_de;
    end
end

endmodule
